#coding: utf-8
"""
prerequisite:
    based on Python 2.7.8, django 1.6
usage:
    1) MVC, control part connect view and model
process:
    1) in view
    from pythonems.public import restFulControl
    def char_all(request, major_id):
        #POST/create, PUT/search
        char_control ={
            "GET": (major_model.Char.createFormat,[],{"char_id": "id",
                                                      "char_name": "name",}),}
        return restFulControl(request, char_control, {"char_major_id": major_id})
    "GET": restful method
    major_model.Char.createFormat: response method
    []: args used in server method
    {}: transformat from js_var_name to server_var_name, here is the dict
    2) in model
    def create(cls, *args, **kwargs):
        aItem = cls()
        aItem = cls.traversal_to_save(aItem, cls.create_dict, **kwargs)
        aItem.save()
        return {"value": True,
                "desp": "",
                "data": list(cls.objects.filter(pk=aItem.pk).values())}

know issues:
    1) could this setanse delete ?
    #client_data["user_id"] = request.user.id
    #client_data["time"] = int(time.time())
    #client_data["today"] = int(datetime.date.today().isoformat().replace("-", ""))
"""
import json
from django.http import HttpResponse

def json_http_response(response_formated_string):
    """args: response_formated_string, should as format
    {"value": False/True
     "desp": u"Invalid request method or user premission",
     "data": [],}"""
    return HttpResponse(json.dumps(response_formated_string))

# ##########
# control
# ##########
def get_action(func_name):
    """ translate for django has_perm. used in get_func_premission
    args: func_name, string
    func_name should start as "create" for "add" permission, "update" for "change" permission
    or "del" for "delete" permission. others are "get" permission
    ex. # will get "add"
    >> get_action("create_major_formated") """
    if func_name.startswith("create"):
        return "add"
    if func_name.startswith("update"):
        return "change"
    if func_name.startswith("del"):
        return "delete"
    return "get"

def get_func_premission(func_item):
    """get permission name for func. used in restful_control
    args: func_item, classmethod in models
    ex. will get "major.add_char
    >> from major.models import Char
    >> get_func_premission(Char.create)"""
    class_name = func_item.im_self.__name__.lower() #'Major', 'major'
    func_name = func_item.__name__ #'checkFormat'
    action = get_action(func_name)
    model_name = func_item.im_self.__module__.split(".")[0] #'major.models', "major"
    return model_name + "." + action + "_" + class_name

def invalid_reponse():
    """invalid reponse in restful_control
    json.dumps({"data": [],
    "desp": "Invalid request method or user premission",
    "value": False,})"""
    return HttpResponse('{"data": [],'+
                        '"desp": "Invalid request method or user premission",'+
                        '"value": false}')

#control
def restful_control(request, control, server_kwargs=None):
    """def char_all(request, major_id):
    #POST/create, PUT/search
    char_control ={
        "GET": (major_model.Char.createFormat,[],{"char_id": "id",
                                                  "char_name": "name",}),}
    return restFulControl(request, char_control, {"char_major_id": major_id})
    "GET": restful method
    major_model.Char.createFormat: response method
    []: args used in server method
    {}: transformat from js_var_name to server_var_name, here is the dict"""
    request_method_name = request.method
    #function, *args, **kwargs
    func, args, kwargs_relation = control[request_method_name]
    premission = get_func_premission(func)
    right = request.user.has_perm(premission)
    valid = request.user.is_authenticated() and right
    #print premission + "+" + str(request.user.id) + "+" + str(valid)
    if request_method_name in control and valid:
        #**kwargs
        kwargs = {}
        client_data = json.loads(request.body or "{}")
        if not isinstance(client_data, dict):
            return invalid_reponse()
        #client_data["user_id"] = request.user.id
        #client_data["time"] = int(time.time())
        #client_data["today"] = int(datetime.date.today().isoformat().replace("-", ""))
        for server_var, js_var_name in kwargs_relation.iteritems():
            if js_var_name in client_data:
                kwargs[server_var] = client_data[js_var_name]
        if server_kwargs:
            kwargs.update(server_kwargs)
        kwargs["login_user_id"] = request.user.id
        #action
        return json_http_response(func(*args, **kwargs))
    return invalid_reponse()
